package controllers

import java.io.File

import dao._
import implicits.Implicits._
import javax.inject.Inject
import models.Tables._
import org.apache.commons.io.FileUtils
import org.joda.time.DateTime
import play.api.libs.json.Json
import play.api.mvc.{AbstractController, ControllerComponents}
import shared.VarTool
import tool.{FileTool, FormTool, Tool}
import utils.Utils

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future


/**
 * Created by Administrator on 2019/10/23
 */
class MetaboDbController @Inject()(cc: ControllerComponents, formTool: FormTool, configDao: ConfigDao,
                                   missionDao: MissionDao, userDao: UserDao, userKeggInfoDao: UserKeggInfoDao,
                                   metaboDbDao: MetaboDbDao)(implicit val modeDao: ModeDao) extends
  AbstractController(cc) {

  def nameCheck = Action.async { implicit request =>
    val data = FormTool.dbNameForm.bindFromRequest.get
    val userId = Tool.getUserId
    metaboDbDao.selectByNameOp(userId, data.dbName).map { opConfig =>
      opConfig match {
        case Some(y) => Ok(Json.obj("valid" -> false))
        case None =>
          val valid = true
          Ok(Json.obj("valid" -> valid))
      }
    }
  }

  def getMetaboDbById = Action.async { implicit request =>
    val data = FormTool.idForm.bindFromRequest().get
    metaboDbDao.select(data.id).map { x =>
      val json = Utils.getJsonByT(x)
      Ok(Json.toJson(json))
    }
  }

  def updateName = Action.async { implicit request =>
    val dbName = FormTool.dbNameForm.bindFromRequest().get.dbName
    val id = FormTool.idForm.bindFromRequest().get.id
    val userId = Tool.getUserId
    metaboDbDao.select(id).flatMap { row =>
      val newRow = row.copy(dbName = dbName)
      metaboDbDao.update(newRow).map { x =>
        Ok(Json.toJson("success"))
      }
    }
  }

  def detailInfoBefore = Action { implicit request =>
    val data = FormTool.idForm.bindFromRequest().get
    Ok(views.html.user.metaboDbDetailInfo(data.id))
  }

  def getAllUserKeggInfo = Action.async { implicit request =>
    val data = FormTool.idForm.bindFromRequest().get
    userKeggInfoDao.selectAll(data.id).map { keggInfos =>
      val sortRows = if (keggInfos.forall(x => x.index.isInt)) {
        keggInfos.sortBy(_.index.toInt)
      } else keggInfos
      val array = Utils.getArrayByTs(sortRows)
      val json = Json.toJson(array)
      Ok(json)
    }
  }


  def add = Action.async(parse.multipartFormData) { implicit request =>
    val data = FormTool.dbNameForm.bindFromRequest().get
    val file = request.body.file("file").get
    val tmpDir = Tool.createTempDirectory("tmpDir")
    val tmpFile = new File(tmpDir, "tmp.xlsx")
    file.ref.moveTo(tmpFile, true)
    val userId = Tool.getUserId
    val myMessage = FileTool.metaboFileCheck(tmpFile)
    if (!myMessage.valid) {
      Tool.deleteDirectory(tmpDir)
      Future.successful(Ok(Json.obj("error" -> myMessage.message)))
    } else {
      val row = MetaboDbRow(0, userId, data.dbName, new DateTime())
      metaboDbDao.insertAndReturnId(row).flatMap { id =>
        val lines = tmpFile.xlsxLines
        val headers = lines.head
        val keggInfos = lines.drop(1).mapOtherByColumns { columns =>
          val lineMap = headers.zip(columns).toMap
          val name = lineMap("Name")
          val strandardName = lineMap("Standard.name")
          UserKegginfoRow(id, lineMap("Index"), name, strandardName, lineMap.getOrElse("HMDBID", "NA"),
            lineMap.getOrElse("KeggID", "NA"), lineMap("Class"))
        }
        userKeggInfoDao.insertAll(keggInfos)
      }.map { x =>
        Tool.deleteDirectory(tmpDir)
        Ok(Json.toJson("success!"))
      }
    }
  }

  def getAllMetaboDb = Action.async { implicit request =>
    val userId = Tool.getUserId
    metaboDbDao.selectAll(userId).map { rows =>
      val array = Utils.getArrayByTs(rows)
      val json = Json.toJson(array)
      Ok(json)
    }
  }

  def manageBefore = Action { implicit request =>
    Ok(views.html.user.metaboDbManage())
  }

  def deleteById = Action.async { implicit request =>
    val data = FormTool.idForm.bindFromRequest().get
    metaboDbDao.deleteById(data.id).zip(userKeggInfoDao.deleteAll(data.id)).map { x =>
      Ok("success")
    }
  }

}
